import { ref } from "vue";

// 定义 WebSocket 服务的配置选项接口
export interface WebSocketOptions {
  url: string;
  heartbeatInterval?: number;
  heartbeatMessage?: string;
  reconnectInterval?: number;
  maxReconnectAttempts?: number;
}

// 定义事件处理回调函数的类型
type WebSocketCallback = (data: any) => void;

export class WebSocketService {
  private ws: WebSocket | null = null;
  private options: Required<WebSocketOptions>;
  private reconnectAttempts = 0;
  private heartbeatTimer: NodeJS.Timeout | null = null;
  private serverTimeoutTimer: NodeJS.Timeout | null = null;
  private isManualClose = false;

  private eventListeners: Map<string, Set<WebSocketCallback>> = new Map();

  // 使用 ref 创建响应式连接状态
  public isConnected = ref(false);

  constructor(options: WebSocketOptions) {
    this.options = {
      url: options.url,
      heartbeatInterval: options.heartbeatInterval || 30000,
      heartbeatMessage: options.heartbeatMessage || '{"type":"ping"}',
      reconnectInterval: options.reconnectInterval || 5000,
      maxReconnectAttempts: options.maxReconnectAttempts || 10
    };
    this.connect();
  }

  // 连接 WebSocket
  public connect() {
    if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) {
      console.log("WebSocket is already connected or connecting.");
      return;
    }

    try {
      this.ws = new WebSocket(this.options.url);
      this.initEventListeners();
    } catch (error) {
      console.error("Failed to create WebSocket connection:", error);
      this.reconnect();
    }
  }

  // 初始化 WebSocket 事件监听
  private initEventListeners() {
    if (!this.ws) return;

    this.ws.onopen = () => {
      console.log("WebSocket connected successfully.");
      this.isConnected.value = true;
      this.reconnectAttempts = 0;
      this.isManualClose = false;
      this.startHeartbeat();
      this.dispatchEvent("open", null);
    };

    this.ws.onmessage = event => {
      this.resetHeartbeat();
      try {
        const data = JSON.parse(event.data);
        this.dispatchEvent("message", data);
        if (data && data.type) {
          this.dispatchEvent(data.type, data.data);
        }
      } catch (error) {
        console.error("Failed to parse message data:", error);
        this.dispatchEvent("error", "Failed to parse message data");
      }
    };

    this.ws.onclose = event => {
      console.log("WebSocket connection closed.", event);
      this.isConnected.value = false;
      this.stopHeartbeat();
      this.dispatchEvent("close", event);
      if (!this.isManualClose) {
        this.reconnect();
      }
    };

    this.ws.onerror = error => {
      console.error("WebSocket error:", error);
      this.dispatchEvent("error", error);
    };
  }

  // 发送消息
  public send(data: object | string) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      const message = typeof data === "string" ? data : JSON.stringify(data);
      this.ws.send(message);
    } else {
      console.error("WebSocket is not connected. Message not sent.");
    }
  }

  // 手动关闭连接
  public close() {
    if (this.ws) {
      this.isManualClose = true;
      this.ws.close();
    }
  }

  // 重连机制
  private reconnect() {
    if (this.reconnectAttempts < this.options.maxReconnectAttempts) {
      this.reconnectAttempts++;
      console.log(`Attempting to reconnect... (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})`);
      setTimeout(() => {
        this.connect();
      }, this.options.reconnectInterval);
    } else {
      console.error("Maximum reconnect attempts reached.");
      this.dispatchEvent("reconnect_failed", null);
    }
  }

  // 心跳机制
  private startHeartbeat() {
    this.heartbeatTimer = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.send(this.options.heartbeatMessage);
        this.serverTimeoutTimer = setTimeout(() => {
          console.warn("Server timeout, closing connection to trigger reconnect.");
          this.ws?.close();
        }, this.options.heartbeatInterval / 2);
      }
    }, this.options.heartbeatInterval);
  }

  private resetHeartbeat() {
    if (this.heartbeatTimer) clearTimeout(this.heartbeatTimer);
    if (this.serverTimeoutTimer) clearTimeout(this.serverTimeoutTimer);
    this.startHeartbeat();
  }

  private stopHeartbeat() {
    if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
    if (this.serverTimeoutTimer) clearTimeout(this.serverTimeoutTimer);
  }

  // 事件订阅与分发
  public on(event: string, callback: WebSocketCallback): () => void {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, new Set());
    }
    this.eventListeners.get(event)!.add(callback);
    return () => this.off(event, callback);
  }

  public off(event: string, callback: WebSocketCallback) {
    if (this.eventListeners.has(event)) {
      this.eventListeners.get(event)!.delete(callback);
    }
  }

  private dispatchEvent(event: string, data: any) {
    if (this.eventListeners.has(event)) {
      this.eventListeners.get(event)!.forEach(callback => {
        try {
          callback(data);
        } catch (error) {
          console.error(`Error in WebSocket event listener for '${event}':`, error);
        }
      });
    }
  }
}
